using Microsoft.Extensions.Logging;
using System.Text;
using System.Security.Cryptography;
using System.Text.Json;
using System.Web;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Services.Notification
{
    /// <summary>
    /// 阿里云邮件推送服务提供商
    /// 支持阿里云DirectMail邮件推送服务
    /// </summary>
    public class AliyunEmailProvider : IEmailProvider, IDisposable
    {
        public string Name => "阿里云邮件推送";

        public bool IsConfigured => !string.IsNullOrEmpty(_settings.AccessKeyId) &&
                                   !string.IsNullOrEmpty(_settings.AccessKeySecret) &&
                                   !string.IsNullOrEmpty(_settings.FromAddress);

        private readonly AliyunEmailSettings _settings;
        private readonly ILogger _logger;
        private readonly HttpClient _httpClient;
        private const string ALIYUN_ENDPOINT = "https://dm.{0}.aliyuncs.com/";

        public AliyunEmailProvider(AliyunEmailSettings settings, ILogger logger)
        {
            _settings = settings ?? throw new ArgumentNullException(nameof(settings));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _httpClient = new HttpClient
            {
                Timeout = TimeSpan.FromSeconds(30)
            };
        }

        /// <summary>
        /// 发送邮件
        /// </summary>
        public async Task<EmailSendResult> SendAsync(EmailMessage message)
        {
            if (!IsConfigured)
            {
                return new EmailSendResult
                {
                    Success = false,
                    ErrorMessage = "阿里云邮件提供商未正确配置",
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }

            try
            {
                var parameters = BuildRequestParameters(message);
                var requestUrl = string.Format(ALIYUN_ENDPOINT, _settings.Region);
                
                var startTime = DateTime.UtcNow;
                var response = await SendRequest(requestUrl, parameters);
                var endTime = DateTime.UtcNow;

                if (response.Success)
                {
                    _logger.LogDebug(
                        "阿里云邮件发送成功 - 收件人: {To}, 主题: {Subject}, 耗时: {Duration}ms",
                        message.To, message.Subject, (endTime - startTime).TotalMilliseconds);

                    return new EmailSendResult
                    {
                        Success = true,
                        MessageId = response.MessageId,
                        SentAt = endTime,
                        Provider = Name
                    };
                }
                else
                {
                    _logger.LogError(
                        "阿里云邮件发送失败 - 收件人: {To}, 错误: {Error}",
                        message.To, response.ErrorMessage);

                    return new EmailSendResult
                    {
                        Success = false,
                        ErrorMessage = response.ErrorMessage,
                        SentAt = DateTime.UtcNow,
                        Provider = Name
                    };
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "阿里云邮件发送异常 - 收件人: {To}", message.To);
                
                return new EmailSendResult
                {
                    Success = false,
                    ErrorMessage = ex.Message,
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }
        }

        /// <summary>
        /// 测试连接
        /// </summary>
        public async Task<bool> TestConnectionAsync()
        {
            if (!IsConfigured)
            {
                _logger.LogWarning("阿里云邮件提供商未配置，跳过连接测试");
                return false;
            }

            try
            {
                // 使用查询发送统计的API来测试连接
                var parameters = new Dictionary<string, string>
                {
                    ["Action"] = "QuerySendStatistics",
                    ["Version"] = "2018-05-01",
                    ["AccessKeyId"] = _settings.AccessKeyId,
                    ["SignatureMethod"] = "HMAC-SHA1",
                    ["Timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"),
                    ["SignatureVersion"] = "1.0",
                    ["SignatureNonce"] = Guid.NewGuid().ToString(),
                    ["Format"] = "JSON"
                };

                // 添加签名
                var signature = CalculateSignature("GET", parameters);
                parameters["Signature"] = signature;

                var queryString = string.Join("&", parameters.Select(p => $"{p.Key}={HttpUtility.UrlEncode(p.Value)}"));
                var requestUrl = string.Format(ALIYUN_ENDPOINT, _settings.Region) + "?" + queryString;

                var response = await _httpClient.GetAsync(requestUrl);
                var responseContent = await response.Content.ReadAsStringAsync();

                if (response.IsSuccessStatusCode)
                {
                    _logger.LogInformation("阿里云邮件服务连接测试成功");
                    return true;
                }
                else
                {
                    _logger.LogError("阿里云邮件服务连接测试失败 - 响应: {Response}", responseContent);
                    return false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "阿里云邮件服务连接测试异常");
                return false;
            }
        }

        /// <summary>
        /// 构建请求参数
        /// </summary>
        private Dictionary<string, string> BuildRequestParameters(EmailMessage message)
        {
            var parameters = new Dictionary<string, string>
            {
                ["Action"] = "SendMail",
                ["Version"] = "2018-05-01",
                ["AccessKeyId"] = _settings.AccessKeyId,
                ["SignatureMethod"] = "HMAC-SHA1",
                ["Timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"),
                ["SignatureVersion"] = "1.0",
                ["SignatureNonce"] = Guid.NewGuid().ToString(),
                ["Format"] = "JSON",
                
                // 邮件参数
                ["AccountName"] = !string.IsNullOrEmpty(message.From) ? message.From : _settings.FromAddress,
                ["FromAlias"] = !string.IsNullOrEmpty(message.FromName) ? message.FromName : _settings.FromName,
                ["ToAddress"] = message.To,
                ["Subject"] = message.Subject,
                ["AddressType"] = "1" // 0表示随机账号，1表示发信地址
            };

            // 设置邮件内容
            if (!string.IsNullOrEmpty(message.HtmlBody))
            {
                parameters["HtmlBody"] = message.HtmlBody;
            }

            if (!string.IsNullOrEmpty(message.TextBody))
            {
                parameters["TextBody"] = message.TextBody;
            }

            // 如果没有指定内容，使用TextBody
            if (string.IsNullOrEmpty(message.HtmlBody) && string.IsNullOrEmpty(message.TextBody))
            {
                parameters["TextBody"] = "邮件内容";
            }

            return parameters;
        }

        /// <summary>
        /// 发送请求
        /// </summary>
        private async Task<AliyunEmailResponse> SendRequest(string baseUrl, Dictionary<string, string> parameters)
        {
            try
            {
                // 计算签名
                var signature = CalculateSignature("POST", parameters);
                parameters["Signature"] = signature;

                // 构建POST请求体
                var formData = new FormUrlEncodedContent(parameters);
                
                var response = await _httpClient.PostAsync(baseUrl, formData);
                var responseContent = await response.Content.ReadAsStringAsync();

                if (response.IsSuccessStatusCode)
                {
                    // 解析响应
                    var jsonDoc = JsonDocument.Parse(responseContent);
                    
                    if (jsonDoc.RootElement.TryGetProperty("EnvId", out var envId))
                    {
                        return new AliyunEmailResponse
                        {
                            Success = true,
                            MessageId = envId.GetString()
                        };
                    }
                    else if (jsonDoc.RootElement.TryGetProperty("Code", out var code))
                    {
                        var message = jsonDoc.RootElement.TryGetProperty("Message", out var msg) 
                            ? msg.GetString() : "未知错误";
                        
                        return new AliyunEmailResponse
                        {
                            Success = false,
                            ErrorMessage = $"阿里云错误 ({code.GetString()}): {message}"
                        };
                    }
                }

                return new AliyunEmailResponse
                {
                    Success = false,
                    ErrorMessage = $"HTTP错误: {response.StatusCode}, 响应: {responseContent}"
                };
            }
            catch (Exception ex)
            {
                return new AliyunEmailResponse
                {
                    Success = false,
                    ErrorMessage = ex.Message
                };
            }
        }

        /// <summary>
        /// 计算签名
        /// </summary>
        private string CalculateSignature(string httpMethod, Dictionary<string, string> parameters)
        {
            // 移除签名参数
            var signParams = parameters.Where(p => p.Key != "Signature").ToDictionary(p => p.Key, p => p.Value);
            
            // 按key排序
            var sortedParams = signParams.OrderBy(p => p.Key).ToList();
            
            // 构建规范化查询字符串
            var canonicalizedQuery = string.Join("&", sortedParams.Select(p => 
                $"{UrlEncode(p.Key)}={UrlEncode(p.Value)}"));
            
            // 构建待签名字符串
            var stringToSign = $"{httpMethod}&{UrlEncode("/")}&{UrlEncode(canonicalizedQuery)}";
            
            // 计算签名
            var key = _settings.AccessKeySecret + "&";
            using var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(key));
            var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
            
            return Convert.ToBase64String(hash);
        }

        /// <summary>
        /// URL编码
        /// </summary>
        private static string UrlEncode(string value)
        {
            return HttpUtility.UrlEncode(value, Encoding.UTF8)
                .Replace("+", "%20")
                .Replace("*", "%2A")
                .Replace("%7E", "~");
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            _httpClient?.Dispose();
        }
    }

    /// <summary>
    /// 阿里云邮件响应模型
    /// </summary>
    internal class AliyunEmailResponse
    {
        public bool Success { get; set; }
        public string? MessageId { get; set; }
        public string? ErrorMessage { get; set; }
    }
}
